#pragma once
#include "bondlib.h"
#include <qbprotocol/include/SSQBAModel.h>
#include <core/strings/TinyString.h>
#include <core/container/SHash.h>
#include <core/sync/lock.h>
#include <string>
/*
	[内存优化][scofined.qi]
	功能:	只有键值查询,无顺序要求,无迭代要求
	内存优化
		规模: 62428
		尺寸:sizeof(xCSIUint_c)  = 104

	措施:
		1.构建一个新的结构体xCSIUintCompact取代xCSIUint_c,由客户端内部使用,
		    移除xCSIUint_c中的m_bond_key和m_listedmarket字段
			大小由原先的104减小到52,减少一半
		2.由于主键是CombBondKey,因此可以借鉴BondContainer中的主键表
			鉴于xCSIUintCompact结构体大小过大,为52,如果使用哈希表,空间浪费严重
			这种数据结构,最好使用F14Table,后续实现好再替换
			前期使用map

			绝大多数ComBondKey可以用ComBondKeyCompact来表示
			少量的ComBondKey直接用字符串来表示
			因此,可以将数据放在两个map中
			简便省事,直接用std::map,每个节点浪费16个字节

			针对value尺寸过大的容器,都不推荐使用哈希表,会浪费空间
*/
class xCSIUintCompact
{
public:
	xCSIUintCompact()
	{
		clear();
	}
public:
	double		m_dCleanPriceMaturity;		//到期净价
	double		m_dYieldToMaturity;			//到期收益率
	double		m_dModifiedDurationMarturity;//到期修正久期

	double		m_dCleanPriceExercise;		//行权净价
	double		m_dYieldToExercise;			//行权收益率
	double		m_dModifiedDurationExercise;//行权修正久期

	UINT		m_nDate;					//日期

	xCSIUintCompact(const xCSIUint_c& csiu):
		m_nDate(csiu.m_nDate),
		m_dCleanPriceMaturity(csiu.m_dCleanPriceMaturity),
		m_dYieldToMaturity(csiu.m_dYieldToMaturity),
		m_dModifiedDurationMarturity(csiu.m_dModifiedDurationMarturity),
		m_dCleanPriceExercise(csiu.m_dCleanPriceExercise),
		m_dYieldToExercise(csiu.m_dYieldToExercise),
		m_dModifiedDurationExercise(csiu.m_dModifiedDurationExercise)
	{

	}
	xCSIUintCompact& operator=(const  xCSIUint_c& csiu)
	{
		m_nDate = csiu.m_nDate;
		m_dCleanPriceMaturity = csiu.m_dCleanPriceMaturity;
		m_dYieldToMaturity = csiu.m_dYieldToMaturity;
		m_dModifiedDurationMarturity = csiu.m_dModifiedDurationMarturity;
		m_dCleanPriceExercise = csiu.m_dCleanPriceExercise;
		m_dYieldToExercise = csiu.m_dYieldToExercise;
		m_dModifiedDurationExercise = csiu.m_dModifiedDurationExercise;
		return *this;
	}
	void GetCSIU(xCSIUint_c& csiu)
	{
		csiu.m_nDate = m_nDate;
		csiu.m_dCleanPriceMaturity = m_dCleanPriceMaturity;
		csiu.m_dYieldToMaturity = m_dYieldToMaturity;
		csiu.m_dModifiedDurationMarturity = m_dModifiedDurationMarturity;
		csiu.m_dCleanPriceExercise = m_dCleanPriceExercise;
		csiu.m_dYieldToExercise = m_dYieldToExercise;
		csiu.m_dModifiedDurationExercise = m_dModifiedDurationExercise;
	}
	void clear()
	{
		m_dCleanPriceMaturity = _INVALID_CSI_VALUE;
		m_dYieldToMaturity = _INVALID_CSI_VALUE;
		m_dModifiedDurationMarturity = _INVALID_CSI_VALUE;

		m_dCleanPriceExercise = _INVALID_CSI_VALUE;
		m_dYieldToExercise = _INVALID_CSI_VALUE;
		m_dModifiedDurationExercise = _INVALID_CSI_VALUE;
		memset(this, 0, sizeof(xCSIUint_c));
	}

	inline bool IsHaveYieldToExercise(){ return m_dYieldToExercise > _INVALID_CSI_VALUE; }
	inline bool IsHaveCleanPriceExercise(){ return m_dCleanPriceExercise > _INVALID_CSI_VALUE; }
	inline bool IsModifiedDurationExercise(){ return m_dModifiedDurationExercise > _INVALID_CSI_VALUE; }

	inline bool IsHaveYieldToMarturity(){ return m_dYieldToMaturity > _INVALID_CSI_VALUE; }
	inline bool IsHaveCleanPriceMarturity(){ return m_dCleanPriceMaturity > _INVALID_CSI_VALUE; }
	inline bool IsModifiedDurationMarturity(){ return m_dModifiedDurationMarturity > _INVALID_CSI_VALUE; }

	inline bool IsHaveExercise()
	{
		return (IsHaveYieldToExercise() || IsHaveCleanPriceExercise() || IsModifiedDurationExercise()) ? true : false;
	}

	inline bool IsHaveMarturity()
	{
		return (IsHaveYieldToMarturity() || IsHaveCleanPriceMarturity() || IsModifiedDurationMarturity()) ? true : false;
	}
};



class S_BONDLIB_EXPORT CBondCSInfo
{
public:
	static CBondCSInfo& instance();
	/*
		之所以没有使用KeyString替换std::string,是因为
		GetBondCsiDate中参数类型是std::string,
		改为KeyString后,每次查找都会额外引入一次KeyString分配的开销
		使用TinyString,查找的时候构建伪造一个轻量级的TempTinyString
		无需内存分配,析构的时候也不需要释放内存
	*/
	typedef qb::base::TinyString KeyType;
	struct KeyTypeHasher{
		size_t operator()(const KeyType& key) const{
			return qb::base::time33Hash(key.c_str(), key.size());
		}
	};

	// 以下两种实现皆可,看哪种更省空间,选取一种,将另一种注释掉即可
	// 注意,如果是哈希表,需要考虑逐步扩充,此容器的规模是6w+,map则不用考虑
	typedef std::map<KeyType, xCSIUintCompact> CSInfoMap;
	//typedef std::unordered_map<KeyType, xCSIUintCompact, KeyTypeHasher> CSInfoMap;

	// 以下是改进之前的容器,浪费较为严重
	//typedef std::unordered_map<std::string, xCSIUint_c> UMAP_CSI;
	enum emCSIType
	{
		emCSITypeNull,
		emCSITypeCombine,
		emCSITypeExercise,
		emCSITypeMaturity,		
	};

public:
	qb::base::CSLock& GetMutex() { return m_mutex; }

	void clear();

	void add(const xCSIList_c* pList);
	
	UINT GetBondCsiDate(const std::string& sCombondkey);

	static std::string BuildCombondkey(const std::string& sBondKey, const std::string& sLisMakert);

	bool GetCsiUnit(const std::string& sCombondkey, xCSIUint_c & xUnit);

	double GetCsiYieldForSort(const std::string& sCombondkey);
	double GetCsiCleanPriceForSort(const std::string& sCombondkey);
protected:
	CSInfoMap m_umapCsi;
	qb::base::CSLock m_mutex;

	const std::string m_sSlash;

private:
	CBondCSInfo();
	~CBondCSInfo();
};
